<?php
class  MyEvent
{
    public $event_base;
    public $events;
    public function __construct()
    {
        $this->event_base = new EventBase();
    }

    public function add($fd,$what,$callback,$callback_arg)
    {
        $event = new Event($this->event_base,$fd,$what,$callback,$callback_arg);
        $this->events[intval($fd)] = $event;
        $event->add();
    }

    public function remove($fd)
    {
        $event = $this->events(intval($fd));
        $event->free();
    }

    public function loop()
    {
        $this->event_base->loop();
    }
}

class  Server
{
    public $ip = "";
    public $port = 9999;
    public $path = "./pid.txt";
    public $event;
    public static function daemon()
    {
        umask(0);
        $pid = pcntl_fork();
        if ($pid){
            exit(0);
        }else if ($pid<0){
            die('fork failed\n');
        }

        $sid = posix_setsid();
        $pid = pcntl_fork();

        if ($pid){
            exit(0);
        }else if ($pid<0){
            die('fork failed\n');
        }
        if ($sid<0){
            die('create session failed\n');
        }
    }

    public function __construct($ip,$port=9999)
    {
        $this->ip = $ip;
        $this->port = $port;
        $this->event = new MyEvent();
    }

    public function run()
    {
        if ($GLOBALS['argc']>1){
            $this->sendSignal();
            exit(0);
        }else{
            self::daemon();
        }
        $this->installSignalHandler();
        $this->recordPid();
        $this->start();
    }

    public function sendSignal()
    {
      if (posix_kill($this->getPid(),0)){
          if (strpos($GLOBALS['argv'][1],"stop")!==false){
              posix_kill($this->getPid(),SIGUSR1);
          }
      }
    }

    public function start()
    {
       $domain = sprintf("tcp://%s:%d",$this->ip,$this->port);
       $fd = stream_socket_server($domain,$errno,$errstr);
       if (!$fd){
           die("$errno $errstr\n");
       }
       stream_set_blocking($fd,0);
       $this->event->add($fd,Event::READ|Event::PERSIST,[$this,'requestHandler'],$fd);
       $this->event->loop();
    }

    public function requestHandler($fd)
    {
        $conn = stream_socket_accept($fd);
        fwrite($conn,"HTTP/1.0 200 OK\\r\nContent-Length:2\r\n\r\nHelloworld123");
        fclose($conn);
    }

    public function installSignalHandler()
    {
        $this->event->add(SIGUSR1,Event::SIGNAL,[$this,"handler"],SIGUSR1);
    }

    public function hanlder($signo)
    {
        switch ($signo){
            default:
            case SIGUSR1:
                $this->event->remove($signo);
                $this->stop();
                break;
        }
    }
    public function stop()
    {
        exit(0);
    }
    public function getPid()
    {
        return file_get_contents($this->path);
    }

    public function recordPid()
    {
        file_put_contents($this->path,posix_getpid());
    }
}

$server = new Server("127.0.0.1");
$server->run();